---
title: Consumers
---
import { Link } from "/src/components/Link";

A "Consumer" is a type of widget that bridges the gap between the Widget tree and the Provider tree.

The only real difference between a Consumer and typical widgets is that Consumers
get access to a [Ref]. This enables them to read providers and listen to their changes.
See <Link documentID="concepts2/refs" /> for more information.

Consumers come in a few different flavors, mostly for personal preference. You will find:
- [Consumer], a "builder" widget (similar to [FutureBuilder](https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html)).
  It allows widgets to interact with providers without having to subclass something other than `StatelessWidget` or `StatefulWidget`.
  ```dart
  // We subclass StatelessWidget as usual
  class MyWidget extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      // A FutureBuilder-like widget
      return Consumer(
        // The "builder" callback gives us a "ref" parameter
        builder: (context, ref, _) {
          // We can use that "ref" to listen to providers
          final value = ref.watch(myProvider);
          return Text(value.toString());
        },
      );
    }
  }
  ```
- [ConsumerWidget], a variant of `StatelessWidget` widget.
  Instead of subclassing `StatelessWidget`, you subclass `ConsumerWidget`. It will behave the same,
  besides the fact that `build` receives an extra [WidgetRef] parameter.
  ```dart
  // We subclass ConsumerWidget instead of StatelessWidget
  class MyWidget extends ConsumerWidget {
    // "build" receives an extra parameter
    @override
    Widget build(BuildContext context, WidgetRef ref) {
      // We can use that "ref" to listen to providers
      final value = ref.watch(myProvider);
      return Text(value.toString());
    }
  }
  ```
- [ConsumerStatefulWidget], a variant of `StatefulWidget` widget.  
  Again, instead of subclassing `StatefulWidget`, you subclass `ConsumerStatefulWidget`.
  And instead of `State`, you subclass [ConsumerState].
  The unique part is that [ConsumerState] has a `ref` property.
  ```dart
  // We subclass ConsumerStatefulWidget instead of StatefulWidget
  class MyWidget extends ConsumerStatefulWidget {
    @override
    ConsumerState<MyWidget> createState() => _MyWidgetState();
  }
  // We subclass ConsumerState instead of State
  class _MyWidgetState extends ConsumerState<MyWidget> {
    // A "this.ref" property is available
    @override
    Widget build(BuildContext context) {
      // We can use that "ref" to listen to providers
      final value = ref.watch(myProvider);
      return Text(value.toString());
    }
  }
  ```

Alternatively, you will find extra consumers in the [hooks_riverpod](https://pub.dev/packages/hooks_riverpod) package.
Those combine Riverpod consumers with [flutter_hooks](https://pub.dev/packages/flutter_hooks).
If you don't care about hooks, you can ignore them.


### Which one to use?

The choice of which consumer to use is mostly a matter of personal preference.
You could use [Consumer] for everything. It is a slightly more verbose option than the others.
But this is a reasonable price to pay if you do not like how Riverpod hijacks `StatelessWidget` and `StatefulWidget`.

But if you do not have a strong opinion, we recommend using [ConsumerWidget] (or [ConsumerStatefulWidget] when you need a `State`).

### Why can't we use `StatelessWidget` + `context.watch`?

In alternative packages like [provider](https://pub.dev/packages/provider), you can use `context.watch` to listen to providers.
This works inside any widget, as long as you have a `BuildContext`. So why isn't this the case in Riverpod?

The reason is that relying purely on `BuildContext` instead of a [Ref] would prevent the implementation
of Riverpod's <Link documentID="concepts2/auto_dispose" /> in a reliable way. There _are_ tricks to make
an implementation that "mostly works" with `BuildContext`.
The problem is that there are lots of subtle edge-cases which could silently break the auto-dispose feature.

This would cause memory leaks, but that's not the real issue.  
Automatic disposal is more importantly about stopping the execution of code that is no longer needed.
If auto-dispose fails to dispose a provider, then that provider may continuously perform
network requests in the background.

Riverpod preferred to not compromise on reliability for the sake of a little convenience.

:::note
To alleviate the downsides of having to use [ConsumerWidget]/[ConsumerStatefulWidget] instead of `StatelessWidget`/`StatefulWidget`,
Riverpod offers various refactors in IDEs like VSCode and Android Studio.

![Refactor to Consumer](/img/intro/convert_to_class_provider.gif)

To enable them in your IDE, see <Link documentID="introduction/getting_started" hash="enabling-riverpod_lintcustom_lint" />
:::

[ref]: https://pub.dev/documentation/hooks_riverpod/latest/hooks_riverpod/Ref-class.html
[consumer]: https://pub.dev/documentation/hooks_riverpod/latest/hooks_riverpod/Consumer-class.html
[consumerWidget]: https://pub.dev/documentation/hooks_riverpod/latest/hooks_riverpod/ConsumerWidget-class.html
[consumerStatefulWidget]: https://pub.dev/documentation/hooks_riverpod/latest/hooks_riverpod/ConsumerStatefulWidget-class.html
[consumerState]: https://pub.dev/documentation/hooks_riverpod/latest/hooks_riverpod/ConsumerState-class.html
[widgetref]: https://pub.dev/documentation/hooks_riverpod/latest/hooks_riverpod/WidgetRef-class.html
